package com.budingge.common.ftputils;

import java.io.File;
import java.net.URL;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTPFile;

import com.budingge.common.ftputils.Status.DownloadStatus;
import com.budingge.common.io.FileUtils;

/**
 * ftp 辅助类，借用 ftputls 工具类是实现一些上传文件和下载文件的检验问题
 * 
 * @author weichengshuang
 * 
 */
public class FtpHelper {

	// 日志
	private final static Log log = LogFactory.getLog(FtpHelper.class);

	/**
	 * 上传文件到ftp,步骤，
	 * 
	 * @1：切换ftp工作目录，
	 * @2：上传文件（临时文件名），
	 * @3：检测文件大小，
	 * @4：重命名文件至最终文件名
	 * 
	 * @param ftpUtils
	 * @param remote_path
	 * @param remote_file_name
	 * @param local_path
	 * @param create_dir
	 * @return
	 * @throws Exception
	 */
	public static boolean uploadFile(FtpUtils ftpUtils, String remote_path,
			String remote_file_name, String local_path, boolean create_dir,
			boolean override) throws Exception {
		File local_file = new File(local_path);
		// 判断本地文件是否存在
		if (!local_file.exists()) {
			throw new Exception("not found local file:"
					+ local_file.getAbsolutePath());
		}
		boolean flag = false;
		remote_path = FilenameUtils.separatorsToUnix(remote_path);
		String remote_path_file_name = remote_path + "/" + remote_file_name;

		if (!override && ftpUtils.existFile(remote_path_file_name)) {
			log.debug("exist remote file," + remote_path_file_name);
			flag = true;
		} else {
			flag = ftpUtils.changeWorkingDirectory(remote_path);
			if (!flag && create_dir) {
				if (ftpUtils.createDirectory(remote_path)) {
					flag = ftpUtils.changeWorkingDirectory(remote_path);
				} else {
					throw new Exception("can`t create directory," + remote_path);
				}
			} else {
				log.debug("can`t change working directory," + remote_path);
			}
			if (!flag) {
				throw new Exception("can`t change working directory,"
						+ remote_path);
			}
			String remore_file_name_tmp = remote_path_file_name + ".tmp";
			if (flag) {
				// 上传文件
				try {
					flag = ftpUtils
							.uploadFile(local_path, remore_file_name_tmp);
				} catch (Exception e) {
					log.warn(e.getMessage(), e);
					flag = ftpUtils.deleteFile(remore_file_name_tmp);
					throw e;
				}
			}

			long remote_file_length = -1;
			if (flag) {// 获取远程文件大小
				remote_file_length = ftpUtils.getFilesize(remore_file_name_tmp);
			}
			// 通过判断文件大小来验证上传文件的完整性
			if (flag) {
				flag = local_file.length() == remote_file_length;
			}
			if (flag) {
				// 重命名文件
				flag = ftpUtils.rename(remore_file_name_tmp,
						remote_path_file_name);
			}
			if (!flag) {// 上传失败，删除上传的临时文件
				flag = ftpUtils.deleteFile(remore_file_name_tmp);
			}
		}
		return flag;
	}

	/**
	 * 上传文件到ftp,步骤，
	 * 
	 * @1：切换ftp工作目录，
	 * @2：上传文件（临时文件名），
	 * @3：检测文件大小，
	 * @4：重命名文件至最终文件名
	 * @param ftpUtils
	 * @param remote_path_file
	 * @param local_path
	 * @param create_dir
	 * @return
	 * @throws Exception
	 */
	public static boolean uploadFile(FtpUtils ftpUtils,
			String remote_path_file, String local_path, boolean create_dir,
			boolean override) throws Exception {
		String remote_path = FilenameUtils.getFullPath(remote_path_file);
		String remote_file_name = FilenameUtils.getName(remote_path_file);
		return uploadFile(ftpUtils, remote_path, remote_file_name, local_path,
				create_dir, override);
	}

	/**
	 * 从ftp上下载文件
	 * 
	 * @param ftpUtils
	 * @param remote_path_file
	 * @param local_path_file
	 * @return
	 * @throws Exception
	 */
	public static DownloadStatus downloadFile(FtpUtils ftpUtils,
			String remote_path_file, String local_path_file, boolean override)
			throws Exception {
		log.debug("downing file," + remote_path_file);
		boolean flag = false;
		DownloadStatus downstat = DownloadStatus.Download_New_Failed;
		FTPFile ftpFile = ftpUtils.getFileinfo(remote_path_file);
		long remote_file_length = -1;
		flag = ftpFile != null;
		File local_file = new File(local_path_file);
		if (flag) {
			remote_file_length = ftpFile.getSize();
		}
		long local_file_length = local_file.length();
		log.debug("local file length:" + local_file_length);
		log.debug("remote file length:" + remote_file_length);
		if (override
				|| (local_file_length == 0 || local_file_length < remote_file_length)) {
			// 临时文件
			String local_path_file_tmp = local_path_file + ".tmp";
			File local_file_tmp = new File(local_path_file_tmp);
			if (flag) {
				// 下载到临时文件
				try {
					flag = ftpUtils.download(remote_path_file,
							local_path_file_tmp, "");
				} catch (Exception e) {
					log.warn(e.getMessage(), e);
					local_file_tmp.delete();
					throw e;
				}
			}
			if (flag) {// 判断文件大小来验证文件完整性
				flag = remote_file_length == local_file_tmp.length();
			}

			if (flag) {// 移动文件
				if (local_file.exists()) {
					local_file.delete();
				}
				FileUtils.move(local_path_file_tmp, local_path_file);
				downstat = DownloadStatus.Download_New_Success;
			} else {// 文件下载失败，删除临时文件
				local_file_tmp.delete();
				downstat = DownloadStatus.Download_New_Failed;
			}
		} else {
			// flag = true;
			downstat = DownloadStatus.Local_File_Exist;
		}

		return downstat;
	}

	/**
	 * 从ftp上下载文件
	 * @param ftp_url
	 * @param local_file
	 * @return
	 * @throws Exception
	 */
	public static DownloadStatus downloadFile(String ftp_url, String local_file)
			throws Exception {
		URL url = new URL(ftp_url);
		FTPClientHelper ftpClientHelper = new FTPClientHelper();
		ftpClientHelper.connectServer(ftp_url, 60000, 60000);
		FtpUtils ftpUtils = new FtpUtils(ftpClientHelper.getFtpClient());
		return downloadFile(ftpUtils, url.getPath(), local_file, true);
	}
}
